# -*- coding: utf-8 -*-

from lxml import etree
from fake_useragent import UserAgent
import time
import random
import os
import requests
import shutil
import base64
import re
import json
from fontTools.ttLib import TTFont

requests.packages.urllib3.disable_warnings()  # 忽略HTTPS安全警告

"""
58同城-二手车
字体反爬
https://cs.58.com/ershouche/pn1/?PGTID=0d3036e0-0019-eaab-7b38-ff74de930cbc&ClickID=55&pane=true
"""


class ChuZu():
    def __init__(self):
        ua = UserAgent(use_cache_server=False)  # 禁用服务器缓存
        self.headers = {
            "User-Agent": ua.random,
            "authority": "sh.58.com",
            "method": "GET",
            "path": "/chuzu/?PGTID=0d3090a7-0000-2fcd-3f28-496b220707d5&ClickID=2",
            "scheme": "https",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
            "accept-encoding": "gzip, deflate, br",
            "accept-language": "zh-CN,zh;q=0.9",
            "cache-control": "max-age=0",
            "cookie": 'f=n; commontopbar_new_city_info=523%7C%E9%9E%8D%E5%B1%B1%7Cas; userid360_xml=34065A3D970C36824EB3CC970FA8EEF8; time_create=1588814957885; myLat=""; myLon=""; id58=OZZy816L12b1bRYLY5/UNw==; spm=u-2d2yxv86y3v43nkddh1.BDPCPZ_BT; mcity=as; f=n; commontopbar_new_city_info=523%7C%E9%9E%8D%E5%B1%B1%7Cas; city=as; 58home=as; commontopbar_ipcity=as%7C%E9%9E%8D%E5%B1%B1%7C0; 58tj_uuid=3c54782a-9ae3-40a8-80a9-451f0e855320; new_uv=1; utm_source=market; als=0; wmda_uuid=ac65390dc0bc4c1fe6c70690310f9fe4; wmda_new_uuid=1; wmda_session_id_11187958619315=1586222955132-ba368350-650d-ea1f; sessionid=f7a450d3-eebe-45e6-b3f4-20b74a3942c2; wmda_session_id_1732038237441=1586222955590-f9c3c4da-dce4-f121; wmda_visited_projects=%3B11187958619315%3B1732038237441; new_session=0; gr_user_id=7c2915c6-84f1-4eb3-8cd3-d2e3cddec559; gr_session_id_b26c1cbc59d303d8=73b7b5ed-58df-48d9-a0f9-674314f3e7e4; gr_session_id_b26c1cbc59d303d8_73b7b5ed-58df-48d9-a0f9-674314f3e7e4=true; xxzl_sid="4z8ME2-Tlo-LfP-Rdp-2TgwDZ5s0"; xxzl_deviceid=%2Bx10%2BVyFNkSuZJl1HRL7Bx0BtFDiIxiLNOqV8klF5%2F331AjYFmijhqWly7Iwq4pU; init_refer=; ppStore_fingerprint=A8E210D90CADDEB3E1E96BA12C4F459AB1978D8CB59A57DE%EF%BC%BF1586223051810; xxzl_token="zsaNNrnEsAktcE2N6J53cBoJVljkafKPGJzq9+QFwuTL425FRnzePBrUmg9Iga56in35brBb//eSODvMgkQULA=="; xxzl_cid=abc301f927fe4bc7adaf182310d4eca2; xzuid=44d73496-41ae-4945-a29c-bb12b2977a1f',
            "dnt": "1",
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "none",
            "sec-fetch-user": "?1",
            "upgrade-insecure-requests": "1"
        }
        # 字库
        self.font_dict = {
            "glyph00001": "0",
            "glyph00002": "1",
            "glyph00003": "2",
            "glyph00004": "3",
            "glyph00005": "4",
            "glyph00006": "5",
            "glyph00007": "6",
            "glyph00008": "7",
            "glyph00009": "8",
            "glyph00010": "9",
        }

    # 内容
    def get_contents(self):
        try:
            postData = {

            }
            pageNo = 1
            url = f"https://cs.58.com/ershouche/pn{pageNo}/?PGTID=0d3036e0-0019-eaab-7b38-ff74de930cbc&ClickID=55"
            html = HttpUtils.do_request("GET", url, self.headers, postData)
            # 获取字体文件
            self.get_font_file(html.text)
            # 解析字体
            source_html = self.format_html_source(html.text)
            selector = etree.HTML(source_html)
            root = selector.xpath('//div[@id="list"]//li[@class="info"]')
            for s in root:
                dict_data = dict()
                tmp_url = "".join(s.xpath('./div[@class="info--wrap"]/a/@href'))  # 链接
                dict_data['title'] = "".join(s.xpath('./div//h2//text()')).replace("\n", "").replace(" ", "")  # 标题
                if tmp_url == "":
                    tmp_url = "".join(s.xpath('./div//h2/a/@href'))  # 链接
                    dict_data['title'] = s.xpath('./div//h2/a/text()')[0].replace("\n", "").replace(" ", "")  # 标题

                dict_data['year'] = s.xpath('.//div[@class="info_params"]/text()')[0]  # 年份
                dict_data['gl'] = s.xpath('.//div[@class="info_params"]/text()')[1]  # 公里数
                dict_data['price'] = "".join(s.xpath('.//div[@class="info--price info--price-advanced"]//text()'))\
                    .replace("\n", "").replace(" ", "")  # 价格
                dict_data['url'] = tmp_url
                # print(str(dict_data))
                # 获取详细信息及电话
                time.sleep(1)
                self.get_detail(dict_data)
        except:
            pass


    # 详情信息
    def get_detail(self, dict_data):
        postData = {

        }
        html = HttpUtils.do_request("GET", dict_data['url'], self.headers, postData)

        tid = re.findall(r"TID=(.*?)&", dict_data['url'])[0]
        productid = re.findall(r"productid=(.*?)&", dict_data['url'])[0]
        page_id = re.findall(r"page_id=(.*?)&", dict_data['url'])[0]
        discityid = re.findall(r"dispcid=(.*?)&", dict_data['url'])[0]
        legaokey = f'"productId":"{productid}","pageId":"{page_id}","tid":"{tid}"'
        legaokey = "{" + legaokey + "}"
        id = re.findall(r"(.*?)\.", html.url.split('/')[4])[0][:-1]
        url_tel = f'https://chephone.58.com/api/detail/phone/get/{id}?clientType=4&action=getVC&discityid={discityid}&legaoKey={legaokey}&TID={tid}&abtest257=WBERSHOUCHE_257_1275824607&callback=jQuery18003657638043986362_1586229275675&_=1586229283462'
        html_tel = HttpUtils.do_request("GET", url_tel, self.headers, "")
        tel_json = html_tel.text.replace("jQuery18003657638043986362_1586229275675", "").replace("(", "").replace(")", "")
        tel_json = json.loads(tel_json)
        dict_data['tel'] = tel_json['result']
        # 获取字体文件
        self.get_font_file(html.text)
        # 解析字体
        source_html = self.format_html_source(html.text)
        selector = etree.HTML(source_html)
        # 表显里程
        dict_data['lc'] = selector.xpath('//span[@class="info-meta_val"]/text()')[0]
        # 首次上牌
        dict_data['sp'] = selector.xpath('//span[@class="info-meta_val"]/text()')[1]
        # 排量
        dict_data['pl'] = selector.xpath('//span[@class="info-meta_val"]/text()')[2]
        # 变速箱
        dict_data['auto'] = selector.xpath('//span[@class="info-meta_val"]/text()')[3]
        # 排放标准
        dict_data['pf'] = selector.xpath('//span[@class="info-meta_val"]/text()')[4]
        print(str(dict_data))


    # 获取字体文件,保存TTFont对象
    def get_font_file(self, html):
        try:
            b64 = re.findall(r"base64,(.*?)\'", html, re.S)[0]
            res = base64.b64decode(b64)
            with open("fonts/online_font.ttf", "wb") as f:
                f.write(res)
            self.online_font = TTFont("fonts/online_font.ttf")
            self.online_font.saveXML("./fonts/online.xml")
        except IndexError:
            return

    # 解析字体信息。返回解析后html
    def format_html_source(self, html):
        assert self.online_font, "必须创建字体对象"
        assert os.path.exists("fonts/online.xml"), "请先获取到字体文件。"
        with open("fonts/online.xml", "rb") as f:
            file_data = f.read()
        online_uni_list = self.online_font.getGlyphOrder()[1:]
        file_selector = etree.HTML(file_data)
        for uni2 in online_uni_list:
            code = file_selector.xpath("//cmap//map[@name='{}']/@code".format(uni2))[0]
            dd = "&#x" + code[2:].lower() + ";"
            if dd in html:
                html = html.replace(dd, self.font_dict[uni2])
        return html


if __name__ == '__main__':
    cuzu = ChuZu()
    cuzu.get_contents()